package org.study.jetcache.boot.common;

import com.alibaba.fastjson2.JSON;
import com.alicp.jetcache.*;
import com.google.common.collect.Lists;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.util.*;
import java.util.concurrent.CompletionStage;

/**
 * 缓存操作抽象类：单个、批量
 *
 * @author Administrator
 */
@Slf4j
public abstract class AbstractCacheOperate4All<K, V> implements CacheOperate4All<K, V> {
    /**
     * 缓存前缀
     */
    protected String cacheNamePrefix;

    /**
     * 缓存对象
     */
    protected Cache<K, V> abstractCache;

    /**
     * bean初始化后调用
     */
    @PostConstruct
    public void refreshLoad() {
        try {
            // 设置缓存对象
            abstractCache = this.getCache();
            // 设置缓存前缀
            cacheNamePrefix = this.getCacheNamePrefix();
            // 设置缓存加载器
            abstractCache.config().setLoader(this::loadCache);
        } catch (Exception e) {
            log.error("加载缓存[" + cacheNamePrefix + "]失败", e);
        }
    }

    @Override
    public void addCache(K key, V value) {
        if (Objects.nonNull(key)) {
            try {
                CacheResult cacheResult = abstractCache.PUT(key, value);
                CompletionStage<ResultData> future = cacheResult.future();
                future.thenRun(() -> {
                    if (cacheResult.isSuccess()) {
                        log.info("新增缓存[" + cacheNamePrefix + "]成功[key={},value={}]", key, value);
                    }
                });
            } catch (Exception e) {
                log.error("新增缓存[" + cacheNamePrefix + "]异常", e);
            }
        }
    }

    @Override
    public void addCacheBatch(Map<K, V> map) {
        if (MapUtils.isNotEmpty(map)) {
            try {
                CacheResult cacheResult = abstractCache.PUT_ALL(map);
                CompletionStage<ResultData> future = cacheResult.future();
                future.thenRun(() -> {
                    if (cacheResult.isSuccess()) {
                        log.info("批量新增缓存[" + cacheNamePrefix + "]成功[map={}]", JSON.toJSONString(map));
                    }
                });
            } catch (Exception e) {
                log.error("批量新增缓存[" + cacheNamePrefix + "]异常", e);
            }
        }
    }

    @Override
    public void deleteCache(K key) {
        if (Objects.nonNull(key)) {
            try {
                CacheResult cacheResult = abstractCache.REMOVE(key);
                CompletionStage<ResultData> future = cacheResult.future();
                future.thenRun(() -> {
                    if (cacheResult.isSuccess()) {
                        log.info("删除缓存[" + cacheNamePrefix + "]成功[keys={}]", key);
                    }
                });
            } catch (Exception e) {
                log.error("删除缓存[" + cacheNamePrefix + "]异常", e);
            }
        }
    }

    @Override
    public void deleteCacheBatch(Set<K> keys) {
        if (CollectionUtils.isNotEmpty(keys)) {
            try {
                CacheResult cacheResult = abstractCache.REMOVE_ALL(keys);
                CompletionStage<ResultData> future = cacheResult.future();
                future.thenRun(() -> {
                    if (cacheResult.isSuccess()) {
                        log.info("批量删除缓存[userIdCache]成功[keys={}]", JSON.toJSONString(keys));
                    }
                });
            } catch (Exception e) {
                log.error("批量删除缓存[userIdCache]异常", e);
            }
        }
    }

    @Override
    public V getCacheValue(K key) {
        return abstractCache.get(key);
    }

    @Override
    public List<V> getBatch4List(Set<K> keys) {
        List<V> dataList = Lists.newArrayList();
        Map<K, V> all = abstractCache.getAll(keys);
        if (MapUtils.isNotEmpty(all)) {
            dataList.addAll(all.values());
        }
        return dataList;
    }

    @Override
    public Map<K, V> getBatch4Map(Set<K> keys) {
        return abstractCache.getAll(keys);
    }

    /**
     * 获取缓存对象
     *
     * @return
     */
    protected abstract Cache<K, V> getCache();

    /**
     * 获取缓存名称前缀
     *
     * @return
     */
    protected abstract String getCacheNamePrefix();

    /**
     * 加载缓存对象
     *
     * @param key
     * @return
     */
    protected abstract V loadCache(K key);
}
